package org.jeecg.modules.demo.lydasystem.util;

/**
 * CRC16校验算法（基于提供的C代码实现）
 */
public class CRC16Checker {

    /**
     * CRC16校验计算（与提供的C代码完全对应）
     * @param puchMsg 消息字节数组
     * @param usDataLen 数据长度
     * @return CRC16校验值
     */
    public static int CRC16_Checkout(byte[] puchMsg, int usDataLen) {
        int i, j, crc_reg, check;
        crc_reg = 0xFFFF;

        for (i = 0; i < usDataLen; i++) {
            // 注意：这里需要将byte转换为无符号整数
            int unsignedByte = puchMsg[i] & 0xFF;
            crc_reg = (crc_reg >>> 8) ^ unsignedByte;

            for (j = 0; j < 8; j++) {
                check = crc_reg & 0x0001;
                crc_reg = crc_reg >>> 1;

                if (check == 0x0001) {
                    crc_reg ^= 0xA001;
                }
            }
        }

        return crc_reg;
    }

    /**
     * 计算字符串的CRC16校验码
     * @param data 输入字符串
     * @return 4位十六进制CRC字符串
     */
    public static String calculateCRC(String data) {
        try {
            byte[] bytes = data.getBytes("US-ASCII");
            int crc = CRC16_Checkout(bytes, bytes.length);
            return String.format("%04X", crc);
        } catch (Exception e) {
            System.err.println("CRC计算异常: " + e.getMessage());
            return "0000";
        }
    }

    /**
     * 验证CRC校验码
     * @param data 原始数据
     * @param receivedCRC 接收到的CRC校验码
     * @return 验证是否通过
     */
    public static boolean verifyCRC(String data, String receivedCRC) {
        String calculatedCRC = calculateCRC(data);
        boolean isValid = calculatedCRC.equalsIgnoreCase(receivedCRC);

        System.out.println("CRC验证: 计算值=" + calculatedCRC + ", 接收值=" + receivedCRC + ", 结果=" + isValid);

        if (!isValid) {
            System.err.println("CRC不匹配: 计算=" + calculatedCRC + ", 接收=" + receivedCRC);
        }

        return isValid;
    }

    /**
     * 带调试信息的CRC计算
     */
    public static int CRC16_Checkout_Debug(byte[] puchMsg, int usDataLen) {
        System.out.println("=== CRC16计算调试 ===");
        System.out.println("数据长度: " + usDataLen);
        System.out.print("数据字节: ");
        for (int k = 0; k < usDataLen; k++) {
            System.out.printf("%02X ", puchMsg[k] & 0xFF);
        }
        System.out.println();

        int i, j, crc_reg, check;
        crc_reg = 0xFFFF;
        System.out.printf("初始CRC: 0x%04X%n", crc_reg);

        for (i = 0; i < usDataLen; i++) {
            int unsignedByte = puchMsg[i] & 0xFF;
            System.out.printf("处理字节[%d]: 0x%02X%n", i, unsignedByte);

            int beforeShift = crc_reg;
            crc_reg = (crc_reg >>> 8) ^ unsignedByte;
            System.out.printf("  CRC右移8位: 0x%04X -> 0x%04X, 异或字节后: 0x%04X%n",
                    beforeShift, beforeShift >>> 8, crc_reg);

            for (j = 0; j < 8; j++) {
                check = crc_reg & 0x0001;
                beforeShift = crc_reg;
                crc_reg = crc_reg >>> 1;

                System.out.printf("    位[%d]: CRC=0x%04X, 检查位=%d, 右移后=0x%04X",
                        j, beforeShift, check, crc_reg);

                if (check == 0x0001) {
                    int beforeXor = crc_reg;
                    crc_reg ^= 0xA001;
                    System.out.printf(", 与0xA001异或: 0x%04X -> 0x%04X%n", beforeXor, crc_reg);
                } else {
                    System.out.println();
                }
            }

            System.out.printf("字节[%d]处理完成，CRC: 0x%04X%n", i, crc_reg);
        }

        System.out.printf("最终CRC结果: 0x%04X%n", crc_reg);
        System.out.println("=== CRC计算完成 ===");

        return crc_reg;
    }
}
